namespace Hack.Decompiling.PEA.CLR
{
  using System;
  using System.IO;
  using System.Reflection;
  using System.Reflection.Emit;
  using System.Collections.Generic;
  using System.Runtime;
  using System.Runtime.InteropServices;
  using System.Text;

  [Flags]
  public enum SectionKind : byte
  {
    Reserved = 0x00,
    EHTable = 0x01,
    OptILTable = 0x02,
    FatFormat = 0x40,
    MoreSections = 0x80,
  }

  public class SectionHeader
  {
    #region Statics
    public static SectionHeader of(SectionKind kind, uint dataSize)
    {
      return new SectionHeader(kind, dataSize);
    }
    #endregion
    #region Fields
    protected SectionKind kind = SectionKind.Reserved;
    protected uint dataSize = 0;
    #endregion
    #region Properties
    public virtual SectionKind Kind
    {
      get
      {
        return this.kind;
      }
      set
      {
        this.kind = value;
      }
    }
    public virtual uint DataSize
    {
      get
      {
        return this.dataSize;
      }
      set
      {
        if ((this.dataSize = value) >= 0x100)
        {
          this.IsFatFormat = true;
        }
      }
    }
    public bool IsEHTable
    {
      get
      {
        return (this.Kind & SectionKind.EHTable) != 0;
      }
      set
      {
        if (value)
        {
          this.Kind |= SectionKind.EHTable;
        }
        else
        {
          this.Kind &= ~SectionKind.EHTable;
        }
      }
    }
    public bool IsOptILTable
    {
      get
      {
        return (this.Kind & SectionKind.OptILTable) != 0;
      }
      set
      {
        if (value)
        {
          this.Kind |= SectionKind.OptILTable;
        }
        else
        {
          this.Kind &= ~SectionKind.OptILTable;
        }
      }
    }
    public bool IsFatFormat
    {
      get
      {
        return (this.Kind & SectionKind.FatFormat) != 0;
      }
      set
      {
        if (value)
        {
          this.Kind |= SectionKind.FatFormat;
        }
        else
        {
          this.Kind &= ~SectionKind.FatFormat;
        }
      }
    }
    public bool HasMoreSections
    {
      get
      {
        return (this.Kind & SectionKind.MoreSections) != 0;
      }
      set
      {
        if (value)
        {
          this.Kind |= SectionKind.MoreSections;
        }
        else
        {
          this.Kind &= ~SectionKind.MoreSections;
        }
      }
    }
    #endregion
    #region Constructors
    public SectionHeader(SectionKind kind, uint dataSize)
    {
      this.Kind = kind;
      this.DataSize = dataSize;
    }
    #endregion
    #region Methods
    public virtual SectionHeader Write(BinaryWriter writer)
    {
      if (writer != null)
      {
        writer.Write((byte)this.Kind);

        byte[] bytes = BitConverter.GetBytes(this.DataSize);
        if (bytes != null && bytes.Length == 4)
        {
          if (this.IsFatFormat)
          {
            writer.Write(bytes[0]);
            writer.Write(bytes[1]);
            writer.Write(bytes[2]);
          }
          else
          {
            writer.Write(bytes[0]);
            writer.Write((byte)0);
            writer.Write((byte)0);
          }
        }
      }
      return this;
    }
    public virtual SectionHeader Read(BinaryReader reader)
    {
      if (reader != null)
      {
        SectionKind kind = (SectionKind)reader.ReadByte();
        int first = (int)reader.ReadByte();
        int second = (int)reader.ReadByte();
        int third = (int)reader.ReadByte();
        if ((kind & SectionKind.FatFormat) != 0)
        {
          this.DataSize =(uint)(third << 24 | second << 8 | first);
        }
        else
        {
          this.DataSize = (uint)first;
        }
      }
      return this;
    }
    #endregion
  }
}
